// @author END
// @date 2022-01-27

import 'dart:convert';

import 'package:aidou/http/api.dart';
import 'package:aidou/http/interceptors/common_parameter_interceptor.dart';
import 'package:aidou/http/interceptors/error_interceptor.dart';
import 'package:aidou/utils/string_util.dart';
import 'package:dio/dio.dart';

class HttpManager {
  static const CONTENT_TYPE_JSON = 'application/json;charset=UTF-8';
  static const CONTENT_TYPE_FORM = 'application/x-www-form-urlencoded';
  static const CONTENT_TYPE_IMAGE = 'image/*';

  static HttpManager? _instance;

  factory HttpManager.getInstance() => _getInstance();

  static _getInstance() => _instance ??= HttpManager._internal();

  Dio _dio = Dio();

  HttpManager._internal() {
    BaseOptions baseOptions = new BaseOptions(
        baseUrl: Api.BASE_URL,
        connectTimeout: 10000,
        receiveTimeout: 3000,
        headers: {
          'content-type': CONTENT_TYPE_JSON,
          'responseType': ResponseType.plain,
        });

    _dio = Dio(baseOptions);
    _dio.interceptors.add(LogInterceptor(responseBody: true));
    _dio.interceptors.add(CommonParameterInterceptor());
    _dio.interceptors.add(ErrorInterceptors());
  }

  Future<Map<String, dynamic>> request(String path,
      {baseUrl, targetUrl, data, options}) async {
    if (!StringUtil.isEmpty(targetUrl)) {
      path = targetUrl;
      _dio.options.baseUrl = '';
    } else {
      if (!StringUtil.isEmpty(baseUrl)) {
        _dio.options.baseUrl = baseUrl;
      } else {
        _dio.options.baseUrl = Api.BASE_URL;
      }
    }

    Response response;
    if (data is FormData || options.method == 'POST') {
      response = await _dio.request(path, data: data, options: options);
    } else {
      response = await _dio.request(path,
          data: data, queryParameters: data, options: options);
    }

    if (response.data is Map) {
      return response.data;
    }
    return jsonDecode(response.data.toString());
  }

  Future<Map<String, dynamic>> get(String path,
      {baseUrl, targetUrl, data}) async {
    var res = await request(path,
        baseUrl: baseUrl,
        targetUrl: targetUrl,
        data: data,
        options: Options(method: 'GET'));
    return res;
  }

  Future<Map<String, dynamic>> post(String path,
      {baseUrl, targetUrl, data}) async {
    var res = await request(path,
        baseUrl: baseUrl,
        targetUrl: targetUrl,
        data: data,
        options: Options(method: 'POST'));

    return res;
  }
}
